package com.yihu.wlyy.service.app.followup;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.yihu.wlyy.entity.follow.FollowUpItemRecord;
import com.yihu.wlyy.entity.follow.FollowUpItemRecordAnswer;
import com.yihu.wlyy.entity.follow.FollowUpPlan;
import com.yihu.wlyy.entity.follow.FollowUpPlanStage;
import com.yihu.wlyy.entity.follow.FollowUpPlanStageItem;
import com.yihu.wlyy.entity.follow.FollowUpPlanStageItemQuestion;
import com.yihu.wlyy.entity.follow.FollowUpPlanStageItemQuestionOption;
import com.yihu.wlyy.entity.follow.FollowUpSummary;
import com.yihu.wlyy.repository.FollowUpItemRecordAnswerDao;
import com.yihu.wlyy.repository.FollowUpItemRecordDao;
import com.yihu.wlyy.repository.FollowUpPlanDao;
import com.yihu.wlyy.repository.FollowUpPlanStageDao;
import com.yihu.wlyy.repository.FollowUpPlanStageItemDao;
import com.yihu.wlyy.repository.FollowUpPlanStageItemQuestionDao;
import com.yihu.wlyy.repository.FollowUpPlanStageItemQuestionOptionDao;
import com.yihu.wlyy.repository.FollowUpSummaryDao;
import com.yihu.wlyy.service.BaseService;
import com.yihu.wlyy.util.DateUtil;

/**
 * 随访计划执行情况
 * 
 * @author lyr
 * 
 */
@Component
@Transactional(rollbackOn = Exception.class)
public class FollowUpExecutionService extends BaseService {

	@Autowired
	private FollowUpPlanDao planDao;
	@Autowired
	private FollowUpPlanStageDao planStageDao;
	@Autowired
	private FollowUpPlanStageItemDao planStageItemDao;
	@Autowired
	private FollowUpPlanStageItemQuestionDao questionDao;
	@Autowired
	private FollowUpPlanStageItemQuestionOptionDao questionOptionDao;
	@Autowired
	private FollowUpItemRecordDao recordDao;
	@Autowired
	private FollowUpItemRecordAnswerDao reocrdAnswerDao;
	@Autowired
	private FollowUpSummaryDao summaryDao;

	/**
	 * 随访计划执行情况
	 * 
	 * @param plan String 计划标识
	 * @return
	 */
	public JSONObject getPlanDetails(String plan) {
		// 随访计划
		FollowUpPlan followUpPlan = planDao.findByCode(plan);
		// 随访计划阶段
		List<FollowUpPlanStage> stages = planStageDao.findByPlan(plan);
		// 随访计划随访项
		List<FollowUpPlanStageItem> items = planStageItemDao.findByPlanCode(plan);
		// 阶段随访项对应
		Map<String, List<FollowUpPlanStageItem>> stageItems = new HashMap<String, List<FollowUpPlanStageItem>>();

		// 随访计划
		JSONObject planJson = new JSONObject(followUpPlan);

		// 计划下阶段数组
		JSONArray stageArray = new JSONArray();

		if (stages != null) {
			if (items != null) {
				for (FollowUpPlanStageItem item : items) {
					if (stageItems.containsKey(item.getStage())) {
						stageItems.get(item.getStage()).add(item);
					} else {
						List<FollowUpPlanStageItem> itemList = new ArrayList<FollowUpPlanStageItem>();
						itemList.add(item);
						stageItems.put(item.getStage(), itemList);
					}
				}
			}

			for (FollowUpPlanStage stage : stages) {
				// 随访计划阶段
				JSONObject stageJson = new JSONObject(stage);

				if (stageItems.containsKey(stage.getCode())) {
					stageJson.put("items", stageItems.get(stage.getCode()));
				} else {
					List<FollowUpPlanStageItem> itemList = new ArrayList<FollowUpPlanStageItem>();
					stageJson.put("items", itemList);
				}

				stageArray.put(stageJson);
			}
		}

		planJson.put("stages", stageArray);

		return planJson;

	}

	/**
	 * 随访计划调查情况
	 * 
	 * @param item String 随访项标识
	 * @return
	 */
	public JSONArray getItemInvestigation(String item) {
		List<FollowUpPlanStageItemQuestion> questions = questionDao.findByItem(item);
		List<FollowUpPlanStageItemQuestionOption> options = questionOptionDao.findByItem(item);
		List<FollowUpItemRecordAnswer> answers = reocrdAnswerDao.findByItemOrderByCzrqDesc(item);
		Map<String, JSONObject> answerOptions = new HashMap<String, JSONObject>();
		Map<String, JSONArray> quesAnswers = new HashMap<String, JSONArray>();

		if (options != null) {
			for (FollowUpPlanStageItemQuestionOption option : options) {
				answerOptions.put(option.getCode(), new JSONObject(option));
			}
		}

		if (answers != null) {
			// 问题对应答案
			for (FollowUpItemRecordAnswer answer : answers) {
				JSONObject answerJson = new JSONObject(answer);

				if (answer.getOption() != null && !answer.getOption().isEmpty()) {
					if (answerOptions.containsKey(answer.getOption())) {
						answerJson.put("answerOption", answerOptions.get(answer.getOption()));
					} else {
						answerJson.put("answerOption", "");
					}
				}

				if (quesAnswers.containsKey(answer.getQuestion())) {
					quesAnswers.get(answer.getQuestion()).put(answerJson);
				} else {
					JSONArray answerList = new JSONArray();

					answerList.put(answerJson);
					quesAnswers.put(answer.getQuestion(), answerList);
				}
			}
		}

		JSONArray quesArrayJson = new JSONArray();

		if (questions != null) {
			// 生成随访项问题周期纪录回答JSON
			for (FollowUpPlanStageItemQuestion question : questions) {
				JSONObject quesJson = new JSONObject(question);

				if (quesAnswers.containsKey(question.getCode())) {
					quesJson.put("answers", quesAnswers.get(question.getCode()));
				} else {
					quesJson.put("answers", new ArrayList<FollowUpItemRecordAnswer>());
				}

				quesArrayJson.put(quesJson);
			}
		}

		return quesArrayJson;

	}

	/**
	 * 随访计划随访项调查明细
	 * 
	 * @param item String 随访项标识
	 * @return
	 */
	public JSONObject getItemInverstigationDetails(String item) {
		FollowUpPlanStageItem planStageItem = planStageItemDao.findByCode(item);
		List<FollowUpItemRecord> records = recordDao.findByItemOrderByCzrqDesc(item);

		if (planStageItem != null) {
			JSONObject itemJson = new JSONObject(planStageItem);

			if (records != null) {
				itemJson.put("records", records);
			} else {
				itemJson.put("records", new ArrayList<FollowUpItemRecord>());
			}

			return itemJson;
		}

		return new JSONObject();
	}

	/**
	 * 随访纪录作答详细
	 * 
	 * @param item String 随访项标识
	 * @param record String 随访项纪录标识
	 * @return
	 */
	public JSONObject getItemRecordAnswerDetails(String item, String record) {
		FollowUpItemRecord itemRecord = recordDao.findByCode(record);
		List<FollowUpPlanStageItemQuestion> questions = questionDao.findByItem(item);
		List<FollowUpPlanStageItemQuestionOption> options = questionOptionDao.findByItem(item);
		List<FollowUpItemRecordAnswer> answers = reocrdAnswerDao.findByItemAndRecord(item, record);

		if (itemRecord != null) {
			JSONObject itemJson = new JSONObject(itemRecord);

			FollowUpPlan followUpPlan = planDao.findByCode(itemRecord.getPlan());

			itemJson.put("patient", followUpPlan != null ? followUpPlan.getPatient() : "");
			itemJson.put("patientName", followUpPlan != null ? followUpPlan.getPatientName() : "");

			Map<String, List<FollowUpPlanStageItemQuestionOption>> optionsMap = new HashMap<String, List<FollowUpPlanStageItemQuestionOption>>();
			Map<String, List<FollowUpItemRecordAnswer>> answersMap = new HashMap<String, List<FollowUpItemRecordAnswer>>();

			if (options != null) {
				// 问题对应选项
				for (FollowUpPlanStageItemQuestionOption option : options) {
					if (optionsMap.containsKey(option.getQuestion())) {
						optionsMap.get(option.getQuestion()).add(option);
					} else {
						List<FollowUpPlanStageItemQuestionOption> optionList = new ArrayList<FollowUpPlanStageItemQuestionOption>();
						optionList.add(option);
						optionsMap.put(option.getQuestion(), optionList);
					}
				}
			}

			if (answers != null) {
				// 问题对应答案
				for (FollowUpItemRecordAnswer answer : answers) {
					if (answersMap.containsKey(answer.getQuestion())) {
						answersMap.get(answer.getQuestion()).add(answer);
					} else {
						List<FollowUpItemRecordAnswer> answerList = new ArrayList<FollowUpItemRecordAnswer>();
						answerList.add(answer);
						answersMap.put(answer.getQuestion(), answerList);
					}
				}
			}

			if (questions != null) {
				JSONArray quesArrayJson = new JSONArray();

				for (FollowUpPlanStageItemQuestion question : questions) {
					JSONObject quesJson = new JSONObject(question);

					if (optionsMap.containsKey(question.getCode())) {
						quesJson.put("options", optionsMap.get(question.getCode()));
					} else {
						quesJson.put("options", new ArrayList<FollowUpPlanStageItemQuestionOption>());
					}

					if (answersMap.containsKey(question.getCode())) {
						quesJson.put("answers", answersMap.get(question.getCode()));
					} else {
						quesJson.put("answers", new ArrayList<FollowUpItemRecordAnswer>());
					}

					quesArrayJson.put(quesJson);
				}

				itemJson.put("questions", quesArrayJson);
			}

			// 完成情况下获取总结
			if (itemRecord.getStatus() == 2) {
				FollowUpSummary summmary = summaryDao.findByRecordAndType(record, 4);
				itemJson.put("summary", new JSONObject(summmary));
			}

			return itemJson;
		}

		return new JSONObject();
	}

	/**
	 * 随访项详细
	 * 
	 * @param item String 随访项标识
	 * @return
	 */
	public JSONObject getItemDetails(String item) {
		FollowUpPlanStageItem planStageItem = planStageItemDao.findByCode(item);
		List<FollowUpPlanStageItemQuestion> questions = questionDao.findByItem(item);
		List<FollowUpPlanStageItemQuestionOption> options = questionOptionDao.findByItem(item);

		if (planStageItem != null) {
			JSONObject itemJson = new JSONObject(planStageItem);
			Map<String, List<FollowUpPlanStageItemQuestionOption>> optionsMap = new HashMap<String, List<FollowUpPlanStageItemQuestionOption>>();

			if (options != null) {
				// 问题对应选项
				for (FollowUpPlanStageItemQuestionOption option : options) {
					if (optionsMap.containsKey(option.getQuestion())) {
						optionsMap.get(option.getQuestion()).add(option);
					} else {
						List<FollowUpPlanStageItemQuestionOption> optionList = new ArrayList<FollowUpPlanStageItemQuestionOption>();
						optionList.add(option);
						optionsMap.put(option.getQuestion(), optionList);
					}
				}
			}

			if (questions != null) {
				JSONArray quesArrayJson = new JSONArray();

				for (FollowUpPlanStageItemQuestion question : questions) {
					JSONObject quesJson = new JSONObject(question);

					if (optionsMap.containsKey(question.getCode())) {
						quesJson.put("options", optionsMap.get(question.getCode()));
					} else {
						quesJson.put("options", new ArrayList<FollowUpItemRecordAnswer>());
					}

					quesArrayJson.put(quesJson);
				}

				itemJson.put("questions", quesArrayJson);
			}

			return itemJson;
		}

		return new JSONObject();
	}

	/**
	 * 随访项总结提交
	 * 
	 * @param summary FollowUpSummary 随访项总结
	 * @return
	 */
	@Transactional
	public void saveSummary(int type, int status, FollowUpSummary summary) {
		// 提交总结时状态改变
		if (type == 4) {
			FollowUpItemRecord record = recordDao.findByCode(summary.getRecord());
			record.setStatus(status);
		}

		summaryDao.save(summary);
	}

	/**
	 * 计划状态设置
	 * 
	 * @param status
	 * @param planCode
	 */
	public void setPlanStatus(int status, String planCode) {
		FollowUpPlan plan = planDao.findByCode(planCode);
		List<FollowUpPlanStage> stages = planStageDao.findByPlan(planCode);
		List<FollowUpPlanStageItem> items = planStageItemDao.findByPlanCode(planCode);

		// 计划状态修改
		plan.setStatus(status);

		// 计划下阶段状态修改
		for (FollowUpPlanStage stage : stages) {
			if (status == 2) {
				stage.setStatus(status);
			} else if (stage.getStatus() != 2 && stage.getStatus() != 0) {
				stage.setStatus(status);
			}
		}

		// 计划下随访项状态修改
		for (FollowUpPlanStageItem item : items) {
			if (status == 2) {
				item.setStatus(status);
			} else if (item.getStatus() != 2 && item.getStatus() != 0) {
				item.setStatus(status);
			}
		}
	}

	/**
	 * 阶段状态设置
	 * 
	 * @param status
	 * @param stageCode
	 */
	public void setStageStatus(int status, String stageCode) {
		FollowUpPlanStage stage = planStageDao.findByCode(stageCode);
		List<FollowUpPlanStageItem> items = planStageItemDao.findByPlanAndStage(stage.getPlan(), stageCode);

		// 阶段状态修改
		stage.setStatus(status);

		// 阶段下随访项状态修改
		for (FollowUpPlanStageItem item : items) {
			item.setStatus(status);
		}
	}

	/**
	 * 随访项状态设置
	 * 
	 * @param status
	 * @param itemCode
	 */
	public void setItemStatus(int status, String itemCode) {
		FollowUpPlanStageItem item = planStageItemDao.findByCode(itemCode);

		item.setStatus(status);
	}

	/**
	 * 随访代答
	 * 
	 * @param answers List<FollowUpItemRecordAnswer> 随访答案
	 * @throws Exception 
	 */
	public void saveRecordAnswers(List<FollowUpItemRecordAnswer> answers) throws Exception {
		reocrdAnswerDao.save(answers);

		if (answers.size() > 0) {
			FollowUpItemRecord record = recordDao.findByCode(answers.get(0).getRecord());

			if (record != null) {
				FollowUpPlan plan = planDao.findByCode(record.getPlan());

				if (record.getType() == 1) {
					record.setStatus(1);
					plan.setWjFinishAmount(plan.getWjFinishAmount() + 1);
				} else {
					// 得到当前问卷的答案数
					List<FollowUpItemRecordAnswer> answerList = reocrdAnswerDao.findByRecordDistinQuestion(record.getCode());
					// 得到当前问卷的问题数目
					List<FollowUpPlanStageItemQuestion> questions = questionDao.findByItem(record.getItem());

					if (answerList != null && questions != null) {
						if (questions.size() == answerList.size()) {
							record.setStatus(1);
							plan.setTcAmount(plan.getTcFinishAmount() + 1);
						}
					}
				}
			} else {
				throw new Exception("找不到对应随访周期记录！");
			}
		}
	}

	/**
	 * 随访频率变更
	 * 
	 * @param item String 随访项标识
	 * @param frequency JSONObject 频率
	 * @throws Exception 
	 */
	public void changeItemFrequency(String item, JSONObject frequency) throws Exception {
		FollowUpPlanStageItem planStageItem = planStageItemDao.findByCode(item);

		// 设置随访周期、开始时间、周期单位
		planStageItem.setPushBegin(DateUtil.strToDateShort(frequency.getString("pushBegin")));
		planStageItem.setPushCycle(frequency.getInt("pushCycle"));
		planStageItem.setPushCycleUnit(frequency.getInt("pushCycleUnit"));
		Calendar today = Calendar.getInstance();

		if (frequency.getInt("pushType") == 1) {
			planStageItem.setPushEnd(DateUtil.strToDateShort(frequency.getString("pushEnd")));
			Calendar cld = Calendar.getInstance();

			cld.setTime(planStageItem.getPushBegin());

			int unit = Calendar.DATE;

			if (planStageItem.getPushCycleUnit() == 2) {
				unit = Calendar.WEEK_OF_MONTH;
			} else if (planStageItem.getPushCycleUnit() == 3) {
				unit = Calendar.MONTH;
			}

			while (cld.before(planStageItem.getNextPushDate())) {
				cld.add(unit, planStageItem.getPushCycle());
			}

			if (cld.after(planStageItem.getPushEnd())) {
				cld.setTime(planStageItem.getPushEnd());
			}

			if (cld.get(Calendar.YEAR) == today.get(Calendar.YEAR) && cld.get(Calendar.MONTH) == today.get(Calendar.MONTH) && cld.get(Calendar.DATE) == today.get(Calendar.DATE)) {
				cld.add(Calendar.DATE, 1);
			}

			planStageItem.setNextPushDate(cld.getTime());
		} else {
			// 下次执行时间调整
			planStageItem.setPushTimes(frequency.getInt("pushTimes"));
			int executeFinish = recordDao.countByItem(item);
			int executeLeft = planStageItem.getPushTimes() - executeFinish;

			if (executeLeft > 0) {
				Calendar cld = Calendar.getInstance();
				cld.setTime(planStageItem.getPushBegin());

				switch (planStageItem.getPushCycleUnit()) {
				case 1:
					cld.add(Calendar.DATE, executeFinish * planStageItem.getPushCycle());
					break;
				case 2:
					cld.add(Calendar.WEEK_OF_MONTH, executeFinish * planStageItem.getPushCycle());
					break;
				case 3:
					cld.add(Calendar.MONTH, executeFinish * planStageItem.getPushCycle());
					break;
				default:
					break;
				}

				if (cld.get(Calendar.YEAR) == today.get(Calendar.YEAR) && cld.get(Calendar.MONTH) == today.get(Calendar.MONTH) && cld.get(Calendar.DATE) == today.get(Calendar.DATE)) {
					cld.add(Calendar.DATE, 1);
				}

				planStageItem.setNextPushDate(cld.getTime());
			}
		}
	}

	/**
	 * 随访计划编辑
	 * 
	 * @param stages 阶段
	 * @param items 随访项
	 * @param questions 问题
	 * @param options 问题选项
	 */
	public void editPlan(List<FollowUpPlanStage> stages, List<FollowUpPlanStageItem> items, List<FollowUpPlanStageItemQuestion> questions, List<FollowUpPlanStageItemQuestionOption> options) {
		if (stages.size() > 0) {
			planStageDao.save(stages);
		}
		if (items.size() > 0) {
			planStageItemDao.save(items);
		}
		if (questions.size() > 0) {
			questionDao.save(questions);
		}
		if (options.size() > 0) {
			questionOptionDao.save(options);
		}
	}

	/**
	 * 总结获取
	 * 
	 * @param type String 总结类别
	 * @param summary 对应总结标识
	 * @return
	 */
	public JSONObject getSummary(int type, String summary) {
		FollowUpSummary summaryEntity = new FollowUpSummary();

		// 根据总结类型获取对应的总结数据
		switch (type) {
		case 1:
			summaryEntity = summaryDao.findByPlanAndType(summary, type);
			break;
		case 2:
			summaryEntity = summaryDao.findByStageAndType(summary, type);
			break;
		case 3:
			summaryEntity = summaryDao.findByItemAndType(summary, type);
			break;
		case 4:
			summaryEntity = summaryDao.findByRecordAndType(summary, type);
			break;
		default:
			break;
		}

		return summaryEntity != null ? new JSONObject(summaryEntity) : new JSONObject();
	}

	/**
	 * 阶段编辑
	 * 
	 * @param stage
	 * @param stageJson
	 * @throws Exception 
	 */
	public void editStage(String stage, JSONObject stageJson) throws Exception {
		FollowUpPlanStage planStage = planStageDao.findByCode(stage);

		if (planStage != null) {
			// 阶段周期变更
			planStage.setType(stageJson.getInt("type"));
			planStage.setEndDate(DateUtil.strToDateShort(stageJson.getString("endDate")));
			planStage.setTarget(stageJson.getString("target"));
		} else {
			throw new Exception("未找到对应阶段！");
		}
	}
}
